/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/cat.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../macro/head.h"
#include "impl.h"

namespace action
{
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    typedef xos_stl::auto_map< std::string, xos::i_list, thread_lock > PLUGIN_LIST_MAP;
    typedef PLUGIN_LIST_MAP::iterator PLUGIN_LIST_ITER;

    static PLUGIN_LIST_MAP * m_pMap = 0;
    static impl::POOL * pool_ptr = 0;

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    impl::impl()
    {
        m_pAggedObject = 0;
        init_data();
    }

    impl::~impl()
    {
        if( m_pAggedObject )
        {
            m_pAggedObject->set_outter_unknown( 0 );
            xos_stl::release_interface( m_pAggedObject );
        }
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // public method

    int impl::get_addr( POOL *** pppPool, void *** pppGroup, LIST *** pppList, T *** pppObj, void *** pppFields )
    {
        int ret = 0;
        if( pppPool )
        {
            *pppPool = &pool_ptr;
        }
        if( pppGroup )
        {
            *pppGroup = 0;
        }
        if( pppList )
        {
            *pppList = 0;
        }
        if( pppObj )
        {
            *pppObj = 0;
        }
        if( pppFields )
        {
            *pppFields = 0;
        }
        return ret;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    impl::T * impl::get_from_pool( const char * lpszClsName )
    {
        T * pRet = 0;
        {
            xos_stl::auto_lock< PLUGIN_LIST_MAP > lock( m_pMap );
            PLUGIN_LIST_ITER iter = m_pMap->find( lpszClsName );
            if( iter != m_pMap->end() )
            {
                xos::i_list * pList = iter->second;
                pRet = ( T* )pList->front( 0 );
                if( pRet )
                {
                    pList->pop_front();
                }
            }
        }
        if( !pRet )
        {
            pRet = BASE::get_item_from_pool( true );
        }
        return pRet;
    }

    void impl::put_back_to_pool( T * pT, bool bLock )
    {
        xos_stl::auto_lock< PLUGIN_LIST_MAP > lock( m_pMap );
        const char * lpszClsName = pT->class_name();
        PLUGIN_LIST_ITER iter = m_pMap->find( lpszClsName );
        xos::i_list * pList = 0;
        if( iter == m_pMap->end() )
        {
            container()->xos()->create( xos::i_xos::XOS_OBJ_LIST, ( void** )&pList );
            ( *m_pMap )[lpszClsName] = pList;
        }
        else
        {
            pList = iter->second;
        }
        pList->push_back( pT );
    }

    int impl::static_user_init()
    {
        int ret = 0;
        xos_stl::init_obj( m_pMap );
        return ret;
    }

    int impl::static_user_term()
    {
        int ret = 0;
        if( m_pMap )
        {
            for( PLUGIN_LIST_ITER iter = m_pMap->begin(); iter != m_pMap->end(); ++iter )
            {
                xos::i_list * pList = iter->second;
                while( impl * pImpl = ( impl* )pList->front( 0 ) )
                {
                    impl::T * pT = ( impl::T* )pImpl;
                    BASE * pB = pImpl;
                    pList->pop_front();
                    pT->term();
                    pB->put_back_to_pool( pT, true );
                }
                pList->release();
            }
            m_pMap->clear();
            xos_stl::term_obj( m_pMap );
        }
        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int impl::set_agged_obj( icat::i_plugin * pObj )
    {
        xos::i_unknown * pUnk = static_cast< T* >( this )->get_unknown();
        pObj->set_outter_unknown( pUnk );
        m_pAggedObject = pObj;
        return 0;
    }

    icat::i_plugin * impl::get_agged_obj()
    {
        return m_pAggedObject;
    }

    int impl::init()
    {
        int ret = 0;
        return ret;
    }

    int impl::term()
    {
        int ret = 0;
        if( icat::i_agged * pPlugin = ( icat::i_agged * )get_agged_obj() )
        {
            pPlugin->reset();
        }
        init_data();
        return ret;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int impl::init_data()
    {
        int ret = 0;
        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //

} // action
